package com.raymond.utils;

import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpHeaderValues.KEEP_ALIVE;

/**
 * HttpUtil
 *
 * @author :  raymond
 * @version :  1.0
 * @date :  2019/7/16
 */
@Slf4j
public class NettyHttpUtil {
    /**
     * 找不到方法
     * @param ctx 请求上下文
     * @param keepAlive keepAlive
     */
    public static void sendNotFound(ChannelHandlerContext ctx, Boolean keepAlive){
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND);
        makeHeadAndSend(response, ctx, null == keepAlive ? false : keepAlive);
    }

    private static void makeHeadAndSend(DefaultFullHttpResponse httpResponse, ChannelHandlerContext ctx, Boolean isKeepAlive){
        //构造头部
        setLengthAndJsonType(httpResponse);
        //判断是否keepAlive写出数据
        if (isKeepAlive) {
            httpResponse.headers().set(HttpHeaderNames.CONNECTION, KEEP_ALIVE);
            ctx.channel().writeAndFlush(httpResponse);
        } else {
            ctx.channel().writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
        }

    }

    /**
     * 发送ret为成功
     *
     * @param ctx ctx
     * @param keepAlive request的keepAlive
     */
    public static void sendRetSuccess(ChannelHandlerContext ctx, boolean keepAlive) {
        DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, ctx.alloc().heapBuffer());
        httpResponse.content().writeBytes(JSONObject.toJSONString(new Result()).getBytes());
        makeHeadAndSend(httpResponse, ctx, keepAlive);
    }

    /**
     * 自己组装结果集
     *
     * @param ctx ctx
     * @param result      结果集
     * @param keepAlive request里是否包含keepAlive
     */
    public static void sendErrorCode(ChannelHandlerContext ctx, String result, Boolean keepAlive) {
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, ctx.alloc().heapBuffer());
        response.content().writeBytes(result.getBytes());
        makeHeadAndSend(response, ctx, null == keepAlive ? false : keepAlive);
    }
    /**
     * 获取body里的数据并转成json
     *
     * @param message message
     * @return 成功返回内容，否则返回null
     */
    public static JSONObject getJsonBody(FullHttpMessage message) {
        String content = message.content().toString(Charset.defaultCharset());
        try {
            return JSONObject.parseObject(content);
        } catch (Exception e) {
            log.warn("解析body内容失败 > {}" , content, e);
            return null;
        }
    }
    /**
     * 获取body里的数据
     *
     * @param message message
     * @return 成功返回内容，否则返回null
     */
    public static String getContent(FullHttpMessage message) {
        return message.content().toString(Charset.defaultCharset());
    }

    /**
     * 获取是那个方法
     *
     * @param content body里的数据
     * @return 成功返回内容，否则返回null
     */
    public static String getMethod(String content) {
        try {
            return JSONObject.parseObject(content).getString("method");
        } catch (Exception e) {
            log.warn("解析body内容失败 > {}" , content, e);
            return null;
        }

    }

    /**
     * 获取是那个方法
     *
     * @param content body里的数据
     * @return 成功返回内容，否则返回null
     */
    public static String getMethod(JSONObject content) {
        try {
            return content.getString("method");
        } catch (Exception e) {
            log.warn("获取method失败 > {}" , content, e);
            return null;
        }
    }

    /**
     * 获取是那个data
     *
     * @param content body里的数据
     * @return 成功返回内容，否则返回null
     */
    public static String getData(JSONObject content) {
        try {
            return content.getString("data");
        } catch (Exception e) {
            log.warn("获取data失败 > {}" , content, e);
            return null;
        }
    }

    /**
     * 在头部设置长度和json类型
     *
     * @param httpMessage 可以是httpRequest、httpResponse
     */
    private static void setLengthAndJsonType(FullHttpMessage httpMessage) {
        HttpHeaders headers = httpMessage.headers();
        headers.setInt(CONTENT_LENGTH, httpMessage.content().readableBytes());
        //设置头部信息
        headers.set(CONTENT_TYPE, "application/json;charset=utf-8");
    }
}
